package com.zhongan.gateway.filter;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.protocol.HTTP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.zhongan.gateway.bean.Api;
import com.zhongan.gateway.bean.ApiAttribute;
import com.zhongan.gateway.common.constant.GwDeveloperApiConstant;
import com.zhongan.gateway.common.utils.HttpClientUtil;
import com.zhongan.gateway.common.utils.TypeUtil;
import com.zhongan.gateway.dto.RequestBase;
import com.zhongan.gateway.service.ApiService;

/**
 * api调用次数记录
 */
@Component
public class RoutHttpZuulFilter extends ZuulFilter {

    private Logger     logger = LoggerFactory.getLogger(RoutHttpZuulFilter.class);

    @Resource
    private ApiService apiService;

    @Override
    public String filterType() {
        return "route";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        String serviceId = (String) ctx.get("serviceId");
        Api api = (Api) ctx.getRequest().getAttribute("api");
        String serviceType = api.getServiceType();
        return "gw".equals(serviceId) && ctx.sendZuulResponse()
                && !GwDeveloperApiConstant.SERVICETYPE_DUBBO.equals(serviceType);

    }

    @Override
    public Object run() {

        String res = "";
        String url = "";

        RequestContext context = RequestContext.getCurrentContext();
        HttpServletRequest request = context.getRequest();
        RequestBase re = (RequestBase) request.getAttribute("requestBase");

        JSONObject biz = (JSONObject) re.getBizContent();

        //发起http请求
        Api api = (Api) request.getAttribute("api");

        if (!StringUtils.isEmpty(api.getSlbUrl())) {
            if (re.getServiceName() != null && re.getServiceName().startsWith("/")) {
                //参数中不传serviceName，开发者调用网关的url是restful样式，slb地址存的是服务方负载均衡地址
                url = api.getSlbUrl() + re.getServiceName();
            } else {
                //参数中传serviceName，开发者调用网关的url是固定的。slb存的是服务接口完整路径
                url = api.getSlbUrl();
            }
        } else {
            //参数中不传serviceName，开发者调用网关的url是restful样式，slb地址为空
            url = request.getRequestURL().toString().replace(GwDeveloperApiConstant.COMMON_GROOVY_URL, "")
                    .replace(GwDeveloperApiConstant.COMMON_URL, "");
        }
        long start = System.currentTimeMillis();
        logger.info("开始Route Http...url={}", url);
        //type

        String serviceType = api.getServiceType();
        Object[] objs = doHttp(serviceType, url, biz, api.getTimeout(), api.getId(), getHeaders(request));
        if (null != objs && objs.length == 2) {
            res = (String) objs[1];
            Integer statusCode = (Integer) objs[0];
            request.setAttribute("res_status", statusCode);
        }
        logger.info("结束Route Http...timecost={}", System.currentTimeMillis() - start);
        if (!StringUtils.isEmpty(res)) {
            context.set("res", res);
        }
        context.setSendZuulResponse(false);
        logger.info("完成Route Http...");

        return null;

    }

    private Object[] doHttp(String type, String url, JSONObject biz, int timeout, Long apiId,
                            Map<String, String> headers) {
        Object[] res = null;
        try {
            List<ApiAttribute> list = apiService.selectApiAttrs(apiId);
            if (GwDeveloperApiConstant.SERVICETYPE_HTTP_FORM.equals(type)) {

                if (list != null && list.size() == 1) {
                    ApiAttribute aa = list.get(0);
                    //只有一个参数，参数为对象
                    if (aa.getAttributeType().startsWith("com.")) {
                        biz = biz.getJSONObject(aa.getName());
                    }
                }
                res = HttpClientUtil.doPostFormWithStatusCode(url, biz, timeout, headers);

            } else {
                String bizReq = "";
                if (list != null && !list.isEmpty()) {
                    //json只有一个参数
                    ApiAttribute aa = list.get(0);
                    bizReq = TypeUtil.obj2Str(biz.get(aa.getName()));
                }
                res = HttpClientUtil.doPostJsonWithStatusCode(url, bizReq, timeout, headers);
            }
        } catch (Exception e) {
            logger.warn("http请求失败：" + e.getMessage(), e);
        }
        return res;
    }

    private Map<String, String> getHeaders(HttpServletRequest request) {
        Map<String, String> map = new HashMap<String, String>();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            if (HTTP.CONTENT_TYPE.equals(key) || HTTP.CONTENT_LEN.equals(key) || HTTP.USER_AGENT.equals(key)
                    || "Accept-Encoding".equals(key) || HTTP.CONTENT_LEN.equalsIgnoreCase(key)) {
                continue;
            }
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }
}
